// $Id: traits_typedef.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#include <boost/test/unit_test.hpp>
#include <boost/type_traits.hpp>
#include <xpcom/array_traits.hpp>
#include <xpcom/ptr_array.hpp>
#include "interface_def.hpp"

struct A
{
    int n;
};

BOOST_AUTO_TEST_CASE(test_traits_typedef_class)
{
    using namespace xpcom;

    typedef array_traits<A> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, A>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, A>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, A*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, A const *>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, A&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, A const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::ctor_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_pointer)
{
    using namespace xpcom;

    typedef array_traits<A*> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, A*>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, A>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, A*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, A const*>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, A&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, A const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_arithmetic)
{
    using namespace xpcom;

    typedef array_traits<uint32_t> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, uint32_t>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, uint32_t>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, uint32_t*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, const uint32_t*>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, uint32_t&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, const uint32_t&>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::void_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::void_destruct_tag>::value));

    typedef array_traits<double> traits2;
    BOOST_CHECK((boost::is_same<traits2::element_type, double>::value));
    BOOST_CHECK((boost::is_same<traits2::value_type, double>::value));
    BOOST_CHECK((boost::is_same<traits2::pointer, double*>::value));
    BOOST_CHECK((boost::is_same<traits2::const_pointer, const double*>::value));
    BOOST_CHECK((boost::is_same<traits2::reference, double&>::value));
    BOOST_CHECK((boost::is_same<traits2::const_reference, const double&>::value));
    BOOST_CHECK((boost::is_same<traits2::construct_policy_tag, construct_policy::void_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits2::destruct_policy_tag, destruct_policy::void_destruct_tag>::value));

    typedef array_traits<wchar> traits3;
    BOOST_CHECK((boost::is_same<traits3::element_type, wchar>::value));
    BOOST_CHECK((boost::is_same<traits3::value_type, wchar>::value));
    BOOST_CHECK((boost::is_same<traits3::pointer, wchar*>::value));
    BOOST_CHECK((boost::is_same<traits3::const_pointer, const wchar*>::value));
    BOOST_CHECK((boost::is_same<traits3::reference, wchar&>::value));
    BOOST_CHECK((boost::is_same<traits3::const_reference, const wchar&>::value));
    BOOST_CHECK((boost::is_same<traits3::construct_policy_tag, construct_policy::void_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits3::destruct_policy_tag, destruct_policy::void_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_void_ptr)
{
    using namespace xpcom;

    typedef array_traits<void*> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, void*>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, void*>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, void**>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, void* const *>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, void*&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, void* const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::void_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_bool)
{
    using namespace xpcom;

    typedef array_traits<bool> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, bool_t>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, proxy::bool_ref>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, proxy::bool_ref*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, proxy::bool_ref const *>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, proxy::bool_ref&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, proxy::bool_ref const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::void_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_pstring)
{
    using namespace xpcom;

    typedef array_traits<char*> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, char*>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, proxy::pstring_ref<char> >::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, proxy::pstring_ref<char>*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, proxy::pstring_ref<char> const*>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, proxy::pstring_ref<char>&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, proxy::pstring_ref<char> const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));

    typedef array_traits<wchar*> traits2;
    BOOST_CHECK((boost::is_same<traits2::element_type, wchar*>::value));
    BOOST_CHECK((boost::is_same<traits2::value_type, proxy::pstring_ref<wchar> >::value));
    BOOST_CHECK((boost::is_same<traits2::pointer, proxy::pstring_ref<wchar>*>::value));
    BOOST_CHECK((boost::is_same<traits2::const_pointer, proxy::pstring_ref<wchar> const*>::value));
    BOOST_CHECK((boost::is_same<traits2::reference, proxy::pstring_ref<wchar>&>::value));
    BOOST_CHECK((boost::is_same<traits2::const_reference, proxy::pstring_ref<wchar> const &>::value));
    BOOST_CHECK((boost::is_same<traits2::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits2::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_uuid)
{
    using namespace xpcom;

    typedef array_traits<uuid> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, uuid*>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, uuid>::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, uuid*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, uuid const *>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, uuid&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, uuid const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));

    typedef array_traits<uuid*> traits2;
    BOOST_CHECK((boost::is_same<traits2::element_type, uuid*>::value));
    BOOST_CHECK((boost::is_same<traits2::value_type, uuid>::value));
    BOOST_CHECK((boost::is_same<traits2::pointer, uuid*>::value));
    BOOST_CHECK((boost::is_same<traits2::const_pointer, uuid const *>::value));
    BOOST_CHECK((boost::is_same<traits2::reference, uuid&>::value));
    BOOST_CHECK((boost::is_same<traits2::const_reference, uuid const &>::value));
    BOOST_CHECK((boost::is_same<traits2::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits2::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));
}

BOOST_AUTO_TEST_CASE(test_traits_typedef_ptr)
{
    using namespace xpcom;

    typedef ptr_array_traits<IA> traits1;
    BOOST_CHECK((boost::is_same<traits1::element_type, IA*>::value));
    BOOST_CHECK((boost::is_same<traits1::value_type, ref_ptr<IA> >::value));
    BOOST_CHECK((boost::is_same<traits1::pointer, ref_ptr<IA>*>::value));
    BOOST_CHECK((boost::is_same<traits1::const_pointer, ref_ptr<IA> const*>::value));
    BOOST_CHECK((boost::is_same<traits1::reference, ref_ptr<IA>&>::value));
    BOOST_CHECK((boost::is_same<traits1::const_reference, ref_ptr<IA> const &>::value));
    BOOST_CHECK((boost::is_same<traits1::construct_policy_tag, construct_policy::zero_construct_tag>::value));
    BOOST_CHECK((boost::is_same<traits1::destruct_policy_tag, destruct_policy::dtor_destruct_tag>::value));
}
